import java.util.Random;

public class GeneticEvolver extends Thread
{
	public int targetGen = 50;
	public int poolSize = 10;
	int generation = 0;
	GeneticPlayer players[] = new GeneticPlayer[poolSize];
	GeneticPlayer best = null;
	int scores[] = new int[poolSize];

	public GeneticEvolver()
	{
		initializePopulation();
	}

	public void run()
	{
		mate();
		evaluate();
		// TODO: all of this
		// mate population tournament style based on score
		// remember to do random mutation in the mating
		// replace parents with children
	}
	
	public void evaluate()
	{
		int numRounds = 10;
		int score = 0;

		// assign a score for each member of the population, for use later in
		// the heuristic

		for (int aiPlayerN = 0; aiPlayerN < poolSize; aiPlayerN++)
		{
			// scores will be win-loss, ties are 0
			for (int i = 0; i < numRounds; i++)
			{
				scores[aiPlayerN] += oneMatchHeuristic(aiPlayerN);
			}
			
			System.out.println(scores[aiPlayerN]);
		}
	}

	private int oneMatchHeuristic(int aiPlayerN)
	{
		int p1 = 1;
		int p2 = 2;
		Random rand = new Random();
		int opponentIndex = rand.nextInt(poolSize);
		GeneticPlayer player1 = players[aiPlayerN];
		GeneticPlayer player2 = players[opponentIndex];
		player1.setPlayerPiece(1);
		player2.setPlayerPiece(2);
		// TODO Play match against random opponent genome
		TTTGame match = new TTTGame();
		player1.setGame(match);
		player2.setGame(match);
		//AIMatch match = new AIMatch(player1, player2);
		int turn = 1;

		// while you can place pieces, and neither p1 or p2 have won
		while (match.canPlaceAny() && !match.win(1) && !match.win(2))
		{
			// do some moves back and forth until this while loop is ended
			if (turn == 1)
			{
				// call game logic
				if (player1.makeMove())
				{
					// piece has been placed
					turn = 2;
				}
				else
				{
					// System.exit(3);
					// the piece can not be placed
				}

				// test for win, test for cat?
				if (match.win(p1))
				{
					return 1;
				}
			}
			else if (turn == 2)
			{
				// call game logic
				if (player2.makeMove())
				{
					// alright, yay, the piece has been placed
					turn = 1;
				}
				else
				{
					// System.exit(3);
					// the piece can not be placed, go again
				}

				// test for win
				if (match.win(p2))
				{
					// for loss return -1
					return -1;
				}
			}
		}

		// for cat return 0
		return 0;
	}

	public void mate()
	{
		// TODO: crossover from one high heuristic to another
		// tournament selection, best 2 of 4 win
		// copy over the last however many from the second to the first
		// randomly mutate

		Random rand = new Random();
		GeneticPlayer[] tempPool = new GeneticPlayer[poolSize];
		for (int i = 0; i < poolSize; i++)
		{
			int s1 = rand.nextInt(poolSize);
			int s2 = rand.nextInt(poolSize);
			int s3 = rand.nextInt(poolSize);
			int s4 = rand.nextInt(poolSize);
			int p1 = s1;
			int p2 = s3;

			// set p1/p2 to the highest values
			if (scores[s2] > scores[s1])
			{
				p1 = s2;
			}
			if (scores[s4] > scores[s3])
			{
				p2 = s4;
			}
			tempPool[i] = crossover(p1, p2);
		}

		players = tempPool;
	}

	private GeneticPlayer crossover(int ind1, int ind2)
	{
		Random rand = new Random();
		int[] tempGenome = players[ind1].genome;
		int gLength = players[0].genome.length;
		int cutPoint = (rand.nextInt(gLength / 3)) + (gLength / 2);
		for (int i = 0; i < cutPoint; i++)
		{
			tempGenome[i] = players[ind1].genome[i];
		}

		// copy from the cutPoint to the end of the genome from the other
		for (int i = cutPoint; i < gLength; i++)
		{
			tempGenome[i] = players[ind2].genome[i];
		}

		GeneticPlayer retPlayer = new GeneticPlayer();
		//add a random mutation
		if (rand.nextBoolean() && rand.nextBoolean()) //this is sure to happen rarely
		{
			int randIndex = rand.nextInt(players[0].genomeSize);
			//switch some random number in this thing
			//System.out.println(tempGenome[randIndex]+"old");
			tempGenome[randIndex] = rand.nextInt(9);
			//System.out.println(tempGenome[randIndex]+":new\n");
		}
		retPlayer.setGenome(tempGenome);
		
		// TODO Auto-generated method stub
		return retPlayer;
	}

	private void initializePopulation()
	{
		// fill the player population with instances
		for (int i = 0; i < poolSize; i++)
		{
			players[i] = new GeneticPlayer(new TTTGame());
		}
	}

	public GeneticPlayer getBest()
	{
		int bestPlayer = 0;
		// find the best
		for (int i = 1; i < poolSize; i++)
		{
			if (scores[i] > scores[bestPlayer])
			{
				bestPlayer = i;
			}
		}
		players[bestPlayer].serial = bestPlayer;
		return players[bestPlayer];
	}

}
